package com.ms.service.module.datacenterlite;

import java.util.ArrayList;
import java.util.concurrent.ConcurrentHashMap;

import org.json.simple.JSONArray;
import org.json.simple.JSONObject;

import com.ms.game.common.container.GameTypeInfo;
import com.ms.service.error.ErrorCode;
import com.ms.service.module.datacenterlite.constant.DCLiteMessageType;
import com.xpec.c4.db.dao.PlayerKeepSeatDAO;
import com.xpec.c4.db.dao.PlayerKeepSeatLogDAO;
import com.xpec.c4.db.model.PlayerKeepSeatLogModel;
import com.xpec.c4.db.model.PlayerKeepSeatModel;
import com.xpec.c4.db.model.basic.BasicGameModel;
import com.xpec.c4.game.time.TimeSys;
import com.xpec.c4.game.utility.GUID;
import com.xpec.c4.service.contexts.Contexts;

/**
 * 更新保留座位機制
 * 
 * @author TW15012
 *
 */
public class GameModifyKeepSeatAysncCommand extends CentralAsyncCommand {
	/**
	 * 
	 */
	private static final long serialVersionUID = -4689326297314790038L;

	/**
	 * 消息對應method type;
	 */
	public int methodType;

	/**
	 * 保留狀態
	 */
	public boolean isOfflineKeep;

	/**
	 * 遊戲名稱<br>
	 * 對應 {@link GameTypeInfo#getGameType()}
	 */
	public String gameName;

	/**
	 * 遊戲館名稱
	 */
	public String halltype;

	/**
	 * 機台唯一碼
	 */
	public String seatid;

	/**
	 * 座位編號
	 */
	public int machineid;

	/**
	 * 玩家guid
	 */
	public GUID playerGUID;

	/**
	 * keep time out
	 */
	public long timeout;

	/**
	 * 機台狀態
	 */
	public int stat;

	/**
	 * 執行結果
	 */
	public int errorCode;

	@SuppressWarnings("unchecked")
	@Override
	public void asyncExecute() throws Exception {
		ConcurrentHashMap<String, GameKeepSeatAllData> keep = DataCenterLiteModule.getKeepSeat();

		String guid = playerGUID.toString();

		GameKeepSeatAllData allData = keep.get(guid);

		boolean haveCacheData = true;
		if (allData == null) {
			// 如果取不 guid 對應的資料就 new 一個暫時的出來，讓同步鎖可以動作
			haveCacheData = false;
			allData = new GameKeepSeatAllData();
		}

		// 同步鎖
		synchronized (allData) {
			ArrayList<GameKeepSeatData> list = null;
			if (!haveCacheData) // 不在快取 = 直接新增
			{
				PlayerKeepSeatModel model = PlayerKeepSeatDAO.getKeepSeatByGuid(guid);

				GameKeepSeatData data = new GameKeepSeatData();
				data.setSeatid(seatid);
				data.setGameName(gameName);
				data.setHalltype(halltype);
				data.setIsofflinekeep(isOfflineKeep);
				data.setMachineid(machineid);
				data.setTimeout(timeout);
				data.setMachinestat(stat);

				JSONObject obj = data.toJson();
				JSONObject db = new JSONObject();
				JSONArray keeplist = new JSONArray();
				keeplist.add(obj);
				db.put("keep", keeplist);

				if (model == null) {
					model = new PlayerKeepSeatModel();
				}
				model.setGuid(guid);
				model.setContent(db.toJSONString());
				model.setModifytime(TimeSys.currentTimeMills());
				model.setCreatetime(TimeSys.currentTimeMills());

				boolean result = PlayerKeepSeatDAO.modifyKeepSeatData(model);

				errorCode = (result) ? ErrorCode.SUCCESS : ErrorCode.UPDATE_KEEPDATA_ERR;

				if (errorCode == ErrorCode.SUCCESS) {
					list = new ArrayList<GameKeepSeatData>();
					list.add(data);

					GameKeepSeatAllData tmpAllData = new GameKeepSeatAllData();
					tmpAllData.setDataList(list);
					tmpAllData.setDataModel(model);

					keep.put(guid, tmpAllData);

					// 做log
					PlayerKeepSeatLogModel log = new PlayerKeepSeatLogModel();
					log.setStat(PlayerKeepSeatLogModel.ADD);
					log.setGamename(gameName);
					log.setHalltype(halltype);
					log.setSeatid(seatid);
					log.setMachineid(machineid);
					log.setGuid(guid);
					log.setTimeout(timeout);
					log.setIsofflinekeep((isOfflineKeep) ? true : false);
					log.setMachinestat(stat);
					log.setCreatetime(TimeSys.currentTimeMills());
					PlayerKeepSeatLogDAO.addPlayerKeepLog(log);
				}

			} else {
				GameKeepSeatData seat = null;
				ArrayList<GameKeepSeatData> data = allData.getDataList();

				// 不是離線保留
				if (!isOfflineKeep) {
					int count = 0;
					for (GameKeepSeatData o : data) {
						if (!o.isIsofflinekeep()) {
							count++;
						}

						// 指定的座位已經有保留，排除離線保留資料
						if (seatid.equals(o.getSeatid()) && !o.isIsofflinekeep()) {
							errorCode = ErrorCode.ALREADY_KEEPSEAT;
							return;
						}

						// 掛機轉保留使用
						if (o.isIsofflinekeep() && seatid.equals(o.getSeatid())) {
							seat = o;
							break;
						}
					}
				} else {
					// 離線保留相關檢查
					for (GameKeepSeatData o : data) {
						if (o.isIsofflinekeep() && o.getMachinestat() != BasicGameModel.OFFLINE_KEEP_SPIN) {
							errorCode = ErrorCode.HAVE_OFFLINEKEEPDATA;
							return;
						} else if (o.isIsofflinekeep() && o.getMachinestat() == BasicGameModel.OFFLINE_KEEP_SPIN) {
							seat = o;
							break;
						}
					}
				}

				String modeldbid = "";
				PlayerKeepSeatModel model = allData.getDataModel();
				// 沒有keep資料，將新資料加入快取中
				if (seat == null) {
					seat = new GameKeepSeatData();
					seat.setModeldbid(model.getDb_id());
					seat.setSeatid(seatid);
					seat.setGameName(gameName);
					seat.setHalltype(halltype);
					seat.setIsofflinekeep(isOfflineKeep);
					seat.setMachineid(machineid);
					seat.setTimeout(timeout);
					seat.setMachinestat(stat);
					data.add(seat);
				}
				// 如果為keep spin , seat != null
				else {
					seat.setModeldbid(model.getDb_id());
					seat.setSeatid(seatid);
					seat.setGameName(gameName);
					seat.setHalltype(halltype);
					seat.setIsofflinekeep(isOfflineKeep);
					seat.setMachineid(machineid);
					seat.setTimeout(timeout);
					seat.setMachinestat(stat);
				}

				JSONArray save = new JSONArray();
				for (GameKeepSeatData o : data) {
					JSONObject obj = new JSONObject();
					obj.put("seatid", o.getSeatid());
					obj.put("game", o.getGameName());
					obj.put("hall", o.getHalltype());
					obj.put("machineid", o.getMachineid());
					obj.put("timeout", o.getTimeout());
					obj.put("offlinekeep", (o.isIsofflinekeep()) ? 1 : 0);
					obj.put("machinestat", o.getMachinestat());

					save.add(obj);
				}
				JSONObject obj = new JSONObject();
				obj.put("keep", save);

				// 更新資料
				model.setContent(obj.toJSONString());
				model.setModifytime(TimeSys.currentTimeMills());

				boolean result = PlayerKeepSeatDAO.modifyKeepSeatData(model);
				errorCode = (result) ? ErrorCode.SUCCESS : ErrorCode.UPDATE_KEEPDATA_ERR;

				// 放回快取
				if (errorCode == ErrorCode.SUCCESS) {
					keep.put(guid, allData);
					// 做log
					PlayerKeepSeatLogModel log = new PlayerKeepSeatLogModel();
					log.setStat(PlayerKeepSeatLogModel.ADD);
					log.setGamename(gameName);
					log.setHalltype(halltype);
					log.setSeatid(seatid);
					log.setMachineid(machineid);
					log.setGuid(guid);
					log.setTimeout(timeout);
					log.setIsofflinekeep((isOfflineKeep) ? true : false);
					log.setMachinestat(stat);
					log.setCreatetime(TimeSys.currentTimeMills());
					PlayerKeepSeatLogDAO.addPlayerKeepLog(log);
				}
			}
		} // synchronized (allData) {
	}

	@Override
	public void callBackExecute(Object... userData) throws Exception {
		switch (methodType) {
		// 執行到此己回到主執行taskqueue中，所以可用contexts讀取module , contexts在非主執行緒時不可使用
		case DCLiteMessageType.FISH_DM_UPDATEKEEPDATA:
		case DCLiteMessageType.FISH_DM_UPDATEKEEPSPINDATA:
			Contexts.getModule().getBasicprocesser().onUpdatePlayerKeepDataCallBack(errorCode, callbackMethod, userData);
			break;
		}
	}
}